package com.tiance.domainservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.tiance.dal.dao.AuditRecordDAO;
import com.tiance.dal.dao.MemberDAO;
import com.tiance.dal.dao.TcDutyDao;
import com.tiance.dal.dataobject.AuditRecordDO;
import com.tiance.dal.dataobject.MemberDO;
import com.tiance.dal.dataobject.TcDutyDO;
import com.tiance.domainservice.assemble.DOAssemble;
import com.tiance.domainservice.checker.DutyChecker;
import com.tiance.domainservice.domain.DutyDomain;
import com.tiance.domainservice.service.DutyService;
import com.tiance.enums.*;
import com.tiance.exception.BusinessException;
import com.tiance.page.QueryPage;
import com.tiance.utils.MapUtil;
import com.tiance.utils.StringUtil;

import com.tiance.utils.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

/**
 *
 * @author 雷霆
 * @version 1.0.0
 * @date$ 2019/2/14
 *
 * Description：
 *
 * Modification History:
 *
 */
@Service
public class DutyServiceImpl implements DutyService {
    protected static final Logger logger = LoggerFactory.getLogger(DutyServiceImpl.class);

    @Resource
    private TcDutyDao tcDutyDao;
    @Resource
    private MemberDAO memberDAO;

    @Resource
    private AuditRecordDAO auditRecordDAO;

    @Override
    public TcDutyDO addDuty(DutyDomain dutyDomain) throws Exception {

        Map<String, Object> paramMap = MapUtil.params2Map(new Object[]{"applicantId", StringUtil.trimNull(dutyDomain.getApplicantId())},
                new Object[]{"statusScope", dutyDomain.getStatusScope()},
                new Object[]{"startTime", dutyDomain.getStartTime()},
                new Object[]{"endTime", dutyDomain.getEndTime()});
        logger.info("开始查询该申请人是否已存在未完成的值班申请，参数:{}", JSON.toJSONString(paramMap));
        int count = tcDutyDao.queryDutyCount(paramMap);
        logger.info("结束查询该申请人是否已存在未完成的值班申请，返回总数:{}", count);
        if(count>0){
            throw new BusinessException("申请人在该前时间段已存在值班记录，请选择其他时间段!");
        }
        TcDutyDO dutyDO = DOAssemble.assembleTcDutyDO(dutyDomain);
        dutyDO.setDutyType(DutyTypeEnum.SELF.getCode());
        logger.info("开始插入值班数据，参数:{}", JSON.toJSONString(dutyDO));
        int insertCount = tcDutyDao.insert(dutyDO);
        logger.info("结束插入值班数据，是否插入成功:{}", insertCount > 0 ? true : false);
        if (count < 1) {
            throw new BusinessException("插入失败");
        }

        AuditRecordDO auditRecordDO= DOAssemble.assembleAuditRecordDO(dutyDomain);
        auditRecordDO.setEntityType(EntityTypeEnum.DUTY_APPLICANT.getCode());

        auditRecordDO.setEntityId(dutyDO.getId());
        logger.info("开始插入值班审核信息数据，参数:{}", JSON.toJSONString(auditRecordDO));
        Long auditRecordount=auditRecordDAO.insert(auditRecordDO);
        logger.info("结束插入值班审核信息数据，是否插入成功:{}", auditRecordount>0?true:false);
        if(auditRecordount<1){
            throw new BusinessException("值班审核信息插入失败");
        }

        return dutyDO;
    }

    @Override
    public List<TcDutyDO> queryDuty(DutyDomain dutyDomain) {


        Map<String, Object> paramMap = MapUtil.params2Map(new Object[]{"memberId", StringUtil.trimNull(dutyDomain.getMemberId())},
                new Object[]{"statusScope", dutyDomain.getStatusScope()},
                new Object[]{"dutyType", StringUtil.trimNull(dutyDomain.getDutyType())},
                new Object[]{"openid", StringUtil.trimNull(dutyDomain.getOpenid())});
        logger.info("开始查询值班数据总数，参数:{}", JSON.toJSONString(paramMap));
        int count = tcDutyDao.queryDutyCount(paramMap);
        logger.info("开始查询值班数据总数，返回总数:{}", count);


        if (0 == count) {
            return new ArrayList();
        }

        QueryPage queryPage = dutyDomain.getQueryPage();
        queryPage.setTotalItem(count);
        paramMap.put("queryPage", queryPage);
        if (queryPage.getEndRow() == 0) {
            queryPage.setStartRow(queryPage.getPageFristItem());
            queryPage.setEndRow(queryPage.getPageLastItem());
        }

        dutyDomain.setQueryPage(queryPage);
        logger.info("开始查询值班数据列表数据，参数:{}", JSON.toJSONString(paramMap));
        List<TcDutyDO> tcDutyDOList = tcDutyDao.queryDutyList(paramMap);
        logger.info("结束查询值班数据数据，查询结果:{}", JSON.toJSONString(tcDutyDOList));
        return tcDutyDOList;
    }

    @Override
    public void cancel(DutyDomain dutyDomain) {

        logger.info("开始查询值班数据，参数:{}", JSON.toJSONString(dutyDomain.getId()));
        TcDutyDO oldActivityDO = tcDutyDao.selectByPrimaryKey(dutyDomain.getId());
        logger.info("结束查询值班数据，查询结果:{}", JSON.toJSONString(oldActivityDO));
        Validator.assertTrue(DutyStatusEnum.APPLY_CANCEL.getCode().equals(oldActivityDO.getApplicantState()),"该值班记录已取消，请勿重复操作!");
        Validator.assertTrue(DutyStatusEnum.DUTY_FINISH.getCode().equals(oldActivityDO.getApplicantState()),"该值班记录已完成，无法取消!");

        TcDutyDO tcDutyDO = DOAssemble.assembleUpdateTcDutyDO(dutyDomain);
        tcDutyDO.setApplicantState(DutyStatusEnum.APPLY_CANCEL.getCode());
        logger.info("开始更新值班数据，参数:{}", JSON.toJSONString(tcDutyDO));
        int count = tcDutyDao.cancel(tcDutyDO);
        logger.info("结束更新值班数据，是否更新成功:{}", count > 0 ? true : false);
        if (count < 1) {
            throw new BusinessException("更新失败");
        }
    }


    @Override
    public List<TcDutyDO> querySubstituteDutyApplyList(DutyDomain dutyDomain) {


        Map<String, Object> paramMap = MapUtil.params2Map(new Object[]{"memberId", StringUtil.trimNull(dutyDomain.getMemberId())},
                new Object[]{"dutyType", StringUtil.trimNull(dutyDomain.getDutyType())},
                new Object[]{"openid", StringUtil.trimNull(dutyDomain.getOpenid())});
        logger.info("开始查询替班数据总数，参数:{}", JSON.toJSONString(paramMap));
        int count = tcDutyDao.querySubstituteDutyApplyListCount(paramMap);
        logger.info("结束查询替班数据总数，返回总数:{}", count);


        if (0 == count) {
            return new ArrayList();
        }

        QueryPage queryPage = dutyDomain.getQueryPage();
        queryPage.setTotalItem(count);
        paramMap.put("queryPage", queryPage);
        if (queryPage.getEndRow() == 0) {
            queryPage.setStartRow(queryPage.getPageFristItem());
            queryPage.setEndRow(queryPage.getPageLastItem());
        }

        dutyDomain.setQueryPage(queryPage);
        logger.info("开始查询替班数据列表数据，参数:{}", JSON.toJSONString(paramMap));
        List<TcDutyDO> tcDutyDOList = tcDutyDao.querySubstituteDutyApplyList(paramMap);
        logger.info("结束查询替班数据数据，查询结果:{}", JSON.toJSONString(tcDutyDOList));
        return tcDutyDOList;
    }

    @Override
    public void substituteDutyApply(DutyDomain dutyDomain) throws Exception {

        logger.info("开始查询原始值班信息，参数:{}", dutyDomain.getId());
        TcDutyDO originDutyDO = tcDutyDao.selectByPrimaryKey(dutyDomain.getId());
        logger.info("结束查询原始值班信息，返回总数:{}", JSON.toJSONString(originDutyDO));

        Validator.assertTrue(DutyStatusEnum.APPLY_CANCEL.getCode().equals(originDutyDO.getApplicantState()),"该值班记录已取消，无法申请替班!");
        Validator.assertTrue(DutyStatusEnum.DUTY_FINISH.getCode().equals(originDutyDO.getApplicantState()),"该值班记录已完成，无法申请替班!");

        logger.info("开始查询该替班人，参数:{}", dutyDomain.getSubstituteNo());
        MemberDO substituteMemberDO=memberDAO.queryMemberByMemberNo(dutyDomain.getSubstituteNo());
        logger.info("结束查询该替班人，参数:{}", JSON.toJSONString(substituteMemberDO));
        Validator.assertTrue(UseStatusEnum.FORBIDDEN.getCode().equals(substituteMemberDO.getMemberStatus()),"该替班人已被禁用，无法替班!");

        Map<String, Object> paramMap = MapUtil.params2Map(new Object[]{"applicantId", StringUtil.trimNull(substituteMemberDO.getId())},
                new Object[]{"statusScope", dutyDomain.getStatusScope()},
                new Object[]{"startTime", dutyDomain.getStartTime()},
                new Object[]{"endTime", dutyDomain.getEndTime()});
        logger.info("开始查询该替班人是否已存在未完成的值班申请，参数:{}", JSON.toJSONString(paramMap));
        int count = tcDutyDao.queryDutyCount(paramMap);
        logger.info("结束查询该替班人是否已存在未完成的值班申请，返回总数:{}", count);
        if(count>0){
            throw new BusinessException("该替班人在该前时间段已存在值班记录，请选择其他时间段或者其他替班人!");
        }

        TcDutyDO updateTcDutyDO = DOAssemble.assembleSubstituteTcDutyDO(dutyDomain);
        updateTcDutyDO.setSubstituteId(substituteMemberDO.getId());
        logger.info("开始更新值班数据，参数:{}", JSON.toJSONString(updateTcDutyDO));
        int updateCount = tcDutyDao.updateSubstituteDutyApply(updateTcDutyDO);
        logger.info("结束更新值班数据，是否更新成功:{}", updateCount > 0 ? true : false);
        if (count < 1) {
            throw new BusinessException("更新失败");
        }

        TcDutyDO substituteDutyDO = DOAssemble.assembleTcDutyDO(dutyDomain);
        substituteDutyDO.setDutyType(DutyTypeEnum.SUBSTITUTE.getCode());
        logger.info("开始插入替班数据，参数:{}", JSON.toJSONString(substituteDutyDO));
        int insertCount = tcDutyDao.insert(substituteDutyDO);
        logger.info("结束插入替班数据，是否插入成功:{}", insertCount > 0 ? true : false);
        if (count < 1) {
            throw new BusinessException("插入失败");
        }


        AuditRecordDO auditRecordDO= DOAssemble.assembleAuditRecordDO(dutyDomain);
        auditRecordDO.setEntityType(EntityTypeEnum.SUBSTITUTE_DUTY_APPLICANT.getCode());

        auditRecordDO.setEntityId(substituteDutyDO.getId());
        logger.info("开始插入替班审核信息数据，参数:{}", JSON.toJSONString(auditRecordDO));
        Long auditRecordount=auditRecordDAO.insert(auditRecordDO);
        logger.info("结束插入替班审核信息数据，是否插入成功:{}", auditRecordount>0?true:false);
        if(auditRecordount<1){
            throw new BusinessException("替班审核信息插入失败");
        }
    }

    @Override
    public void finish(DutyDomain dutyDomain) {

        logger.info("开始查询值班数据，参数:{}", JSON.toJSONString(dutyDomain.getId()));
        TcDutyDO oldActivityDO = tcDutyDao.selectByPrimaryKey(dutyDomain.getId());
        logger.info("结束查询值班数据，查询结果:{}", JSON.toJSONString(oldActivityDO));
        Validator.assertTrue(DutyStatusEnum.APPLY_CANCEL.getCode().equals(oldActivityDO.getApplicantState()),"该值班记录已取消，无法结束!");
        Validator.assertTrue(DutyStatusEnum.DUTY_FINISH.getCode().equals(oldActivityDO.getApplicantState()),"该值班记录已完成，请勿重复操作!");

        TcDutyDO tcDutyDO = DOAssemble.assembleUpdateTcDutyDO(dutyDomain);
        tcDutyDO.setApplicantState(DutyStatusEnum.APPLY_CANCEL.getCode());
        logger.info("开始更新值班数据，参数:{}", JSON.toJSONString(tcDutyDO));
        int count = tcDutyDao.finish(tcDutyDO);
        logger.info("结束更新值班数据，是否更新成功:{}", count > 0 ? true : false);
        if (count < 1) {
            throw new BusinessException("更新失败");
        }
    }

}
